package com.nd.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.crypto.digest.BCrypt;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nd.dao.AdminMapper;
import com.nd.dao.JurisdictionMapper;
import com.nd.dao.PermissionMapper;
import com.nd.dao.RoleMapper;
import com.nd.pojo.bean.*;
import com.nd.pojo.bo.*;
import com.nd.pojo.vo.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @program: project2mall
 * @description:
 * @author: shit_code_builder
 * @create: 2021-06-05 20:32
 **/
@Service
public class JurisdictionService {

    @Autowired
    JurisdictionMapper jurisdictionMapper;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    PermissionMapper permissionMapper;
    @Autowired
    AdminMapper adminMapper;

    @Transactional
    public void addJurisdictionList(List<Player> playerList){

        for (Player player : playerList) {
            Jurisdiction build = Jurisdiction.builder().id(player.getId()).label(player.getLabel()).pid("0").build();
            jurisdictionMapper.insert(build);
            for (Player.ChildrenBeanX child : player.getChildren()) {
                Jurisdiction build1 = Jurisdiction.builder().pid(player.getId()).label(child.getLabel()).id(child.getId()).build();
                jurisdictionMapper.insert(build1);
                for (Player.ChildrenBeanX.ChildrenBean childChild : child.getChildren()) {
                    Jurisdiction build2 = Jurisdiction.builder().pid(child.getId()).label(childChild.getLabel()).id(childChild.getId()).api(childChild.getApi()).build();
                    jurisdictionMapper.insert(build2);
                }
            }
            }

        }

    public ErrorAndErrno rolePremissionList(RoleBO bo) {
        ErrorAndErrno<ListItems<RoleDataVO>> errorAndErrno = new ErrorAndErrno<>();

        PageHelper.startPage(bo.getPage(),bo.getLimit());

        RoleExample example = new RoleExample();
        example.setOrderByClause(bo.getSort() + " " + bo.getOrder());
        RoleExample.Criteria criteria= example.createCriteria();
        if (bo.getName()!=null||"".equals(bo.getName())) criteria.andNameLike("%" + bo.getName() + "%");
        criteria.andDeletedEqualTo(false);
        List<Role> roles = roleMapper.selectByExample(example);
        ArrayList<RoleDataVO> data = new ArrayList<>();
        for (Role role : roles) {
            DateTime addTime = new DateTime(role.getAddTime());
            DateTime updateTime = new DateTime(role.getUpdateTime());
            RoleDataVO build = new RoleDataVO(role.getDesc(),role.getId(),role.getName(),role.getEnabled(),addTime.toString(),updateTime.toString(),role.getDeleted());
            data.add(build);
        }
        ListItems<RoleDataVO> objectListItems = new ListItems<>(data);
        PageInfo<Role> goodsPageInfo = new PageInfo<>(roles);
        long total = goodsPageInfo.getTotal();
        objectListItems.setTotal(total);
        errorAndErrno.setData(objectListItems);

        return errorAndErrno;
    }
    @Transactional
    public ErrorAndErrno roleUpdate(RoleUpdateBO bo) throws Exception {
        if (bo.isDeleted()) { throw new Exception("该角色已经被删除"); }

        Role role = Role.builder().id(bo.getId())
                .name(bo.getName()).desc(bo.getDesc())
                .enabled(bo.isDeleted()).addTime(DateTime.of((bo.getAddTime()),"yyyy-MM-dd HH:mm:ss"))
                .updateTime(DateTime.of((bo.getUpdateTime()),"yyyy-MM-dd HH:mm:ss")).deleted(bo.isDeleted()).build();
        roleMapper.updateByPrimaryKeySelective(role);

        PermissionExample permissionExample = new PermissionExample();
        permissionExample.createCriteria().andRoleIdEqualTo(bo.getId());

        List<Permission> permissions = permissionMapper.selectByExample(permissionExample);

        for (Permission permission : permissions) {
            permission.setDeleted(true);
            permission.setUpdateTime(DateTime.now());
            permissionMapper.updateByPrimaryKeySelective(permission);

        }


        return new ErrorAndErrno();
    }
    @Transactional
    public ErrorAndErrno<RoleAddVO> roleAdd(String name, String desc) throws Exception {
        DateTime now = DateTime.now();
        Integer i =roleMapper.selectIdByName(name,false);
        if (i!=null) {
            throw new Exception("该用户名已存在");
        }
        Role build = Role.builder().addTime(now).desc(desc).name(name).updateTime(now).deleted(false).enabled(false).build();
        RoleAddVO roleAddVO = RoleAddVO.builder().addTime(now.toString()).updateTime(now.toString()).desc(desc).name(name).build();
        Integer integer = roleMapper.selectIdByName(name, true);
        if (integer!=null) {
            build.setId(integer);
            roleAddVO.setId(integer);
            roleMapper.updateByPrimaryKey(build);
        }else {
            int insert = roleMapper.insert(build);
            Integer integer1 = roleMapper.selectIdByName(name, false);
            roleAddVO.setId(integer1);
        }


        ErrorAndErrno<RoleAddVO> errorAndErrno = new ErrorAndErrno<>();
        errorAndErrno.setData(roleAddVO);
        return errorAndErrno;
    }

    public ErrorAndErrno<PressionVO> selectRolePermission(Integer roleId) {
        ErrorAndErrno<PressionVO> errorAndErrno = new ErrorAndErrno<>();
        PressionVO pressionVO = new PressionVO();
        errorAndErrno.setData(pressionVO);
        PermissionExample permissionExample = new PermissionExample();
        permissionExample.createCriteria().andRoleIdEqualTo(roleId).andDeletedEqualTo(false);
        List<Permission> permissions = permissionMapper.selectByExample(permissionExample);
        if (permissions.size()==1&&"*".equals(permissions.get(0).getPermission())){
            JurisdictionExample example = new JurisdictionExample();
            example.createCriteria().andIdLike("%admin%");
            example.or().andIdLike("%index%");
            List<Jurisdiction> jurisdictions = jurisdictionMapper.selectByExample(example);
            List<String> orders=jurisdictions.stream().map(Jurisdiction::getId).collect(Collectors.toList());
            pressionVO.setAssignedPermissions(orders);
        }else {
            List<String> collect = permissions.stream().map(Permission::getPermission).collect(Collectors.toList());
            pressionVO.setAssignedPermissions(collect);
        }

        List<Player> players = new ArrayList<Player>();
        JurisdictionExample example = new JurisdictionExample();
        JurisdictionExample.Criteria criteria = example.createCriteria().andPidEqualTo("0");

        List<Jurisdiction> jurisdictions = jurisdictionMapper.selectByExample(example);

        for (Jurisdiction jurisdiction : jurisdictions) {
            Player player = new Player();

            player.setId(jurisdiction.getId());
            player.setLabel(jurisdiction.getLabel());
            ArrayList<Player.ChildrenBeanX> childrenBeanXs = new ArrayList<>();
            player.setChildren(childrenBeanXs);

            String id = jurisdiction.getId();
            JurisdictionExample exampleSon = new JurisdictionExample();
            exampleSon.createCriteria().andPidEqualTo(id);
            List<Jurisdiction> jurisdictionsSons = jurisdictionMapper.selectByExample(exampleSon);
            for (Jurisdiction jurisdictionSon : jurisdictionsSons) {
                Player.ChildrenBeanX childrenBeanX = new Player.ChildrenBeanX();

                childrenBeanX.setId(jurisdictionSon.getId());
                childrenBeanX.setLabel(jurisdictionSon.getLabel());
                List<Player.ChildrenBeanX.ChildrenBean> childrenBeans = new ArrayList<>();
                childrenBeanX.setChildren(childrenBeans);

                String sonId = jurisdictionSon.getId();
                JurisdictionExample exampleChildren = new JurisdictionExample();
                exampleChildren.createCriteria().andPidEqualTo(sonId);
                List<Jurisdiction> jurisdictChildren = jurisdictionMapper.selectByExample(exampleChildren);
                for (Jurisdiction jurisdictChild : jurisdictChildren) {
                    Player.ChildrenBeanX.ChildrenBean childrenBean = new Player.ChildrenBeanX.ChildrenBean();

                    childrenBean.setApi(jurisdictChild.getApi());
                    childrenBean.setId(jurisdictChild.getId());
                    childrenBean.setLabel(jurisdictChild.getLabel());

                    childrenBeans.add(childrenBean);
                }
            childrenBeanXs.add(childrenBeanX);
            }
         players.add(player);
        }
        pressionVO.setSystemPermissions(players);

        return errorAndErrno;
    }

    @Transactional
    public ErrorAndErrno addRolePermission(AddPerBO bo) throws Exception {
        if (bo.getRoleId()==1){
            throw new Exception("超级管理员权限不可被修改");
        }
        ErrorAndErrno<Object> objectErrorAndErrno = new ErrorAndErrno<>();
        PermissionExample permissionExample = new PermissionExample();
        PermissionExample.Criteria criteria = permissionExample.createCriteria().andRoleIdEqualTo(bo.getRoleId());

        List<String> permissionsFromBo = bo.getPermissions();
        List<Permission> permissionsAll = permissionMapper.selectByExample(permissionExample);

        criteria.andPermissionEqualTo("*");
        List<Permission> permissionsCheckAll = permissionMapper.selectByExample(permissionExample);



        if (permissionsFromBo.size() == 89&& permissionsCheckAll.size()==1) {//如果为通配符
             return objectErrorAndErrno; }
        else if (permissionsFromBo.size() == 89){
            Permission permission = new Permission();
            permission.setUpdateTime(DateTime.now());
            permission.setDeleted(false);
            permission.setPermission("*");
            permission.setAddTime(DateTime.now());
            permission.setRoleId(bo.getRoleId());
            for (Permission permissionDel : permissionsAll) {
                if (!permissionDel.getDeleted()) {//如果未删除 就删除
                    permissionDel.setDeleted(true);permission.setUpdateTime(DateTime.now());
                    permissionMapper.updateByPrimaryKey(permissionDel);
                }
            }
            permissionMapper.insert(permission);//插入通配权限

        }
        
        else {if (permissionsCheckAll.size()==1){ permissionMapper.deleteByPrimaryKey(permissionsCheckAll.get(0).getId());}////该角色之前的为通配删除通配权限
            for (Permission permission : permissionsAll) {
                if (permissionsFromBo.contains(permission.getPermission())&&permission.getDeleted()) { //原有且被删除 直接更新
                    permission.setDeleted(false);permission.setUpdateTime(DateTime.now());
                    permissionMapper.updateByPrimaryKey(permission);
                }else if (!permissionsFromBo.contains(permission.getPermission())&&!permission.getDeleted()){//未传入 原有为 未删除
                    Permission permission1 = new Permission();
                    permission.setDeleted(true);permission.setUpdateTime(DateTime.now());
                    permissionMapper.updateByPrimaryKey(permission);
                }
                permissionsFromBo.remove(permission.getPermission());//用完后移除原有的剩下的插入
            }
            if (!permissionsFromBo.isEmpty()){
                for (String per : permissionsFromBo) {
                    Permission permission = new Permission();
                    permission.setUpdateTime(DateTime.now());
                    permission.setDeleted(false);
                    permission.setPermission(per);
                    permission.setAddTime(DateTime.now());
                    permission.setRoleId(bo.getRoleId());
                    permissionMapper.insert(permission);
                }
            }
        }

        return objectErrorAndErrno;
    }

    public ErrorAndErrno changePassword(ChangePasswordBO bo) throws Exception {

        if (!bo.getNewPassword().isEmpty()&&!bo.getNewPassword2().isEmpty()&&bo.getNewPassword().equals(bo.getNewPassword2())){
            if (bo.getOldPassword().isEmpty()){
                throw new Exception("旧密码为空");
            }else {
                Subject subject = SecurityUtils.getSubject();
                Admin principal = (Admin) subject.getPrincipal();
                Admin admin = adminMapper.selectByPrimaryKey(principal.getId());
                if (  BCrypt.checkpw(bo.getOldPassword(),admin.getPassword())){
                    admin.setPassword(BCrypt.hashpw(bo.getNewPassword()));
                    adminMapper.updateByPrimaryKey(admin);
                }else {
                    throw new Exception("旧密码输入错误");
                }
            }
        }else {
            throw new Exception("新密码或者确认密码为空,请重试");
        }
    return new ErrorAndErrno();
    }
}

